<?php

namespace App\Api\Controllers;


use App\Http\Controllers\LogController;
use App\Http\Controllers\WeChat\WxTrait;
use App\Models\BalanceRecord;
use App\Models\Campus;
use App\Models\Cart;
use App\Models\DealRecord;
use App\Models\Depot;
use App\Models\Goods;
use App\Models\MatchPool;
use App\Models\Notice;
use App\Models\Order;
use App\Models\OrderGoods;
use App\Models\OrderUser;
use App\Models\PlatformIncome;
use App\Models\University;
use App\Models\User;
use App\Models\WebConfig;
use Dingo\Api\Http\Request;
use Dingo\Api\Routing\Helpers;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use EasyWeChat\Payment\Order as PayOrder;


class OrderController extends Controller
{
    use Helpers;
    use WxTrait;
    private $needMatchData;//需要进行最优匹配的商品数据
    private $matchedData;//已经指定了卖家的商品数据

    /**获取全部订单
     * 请求参数：order_status
     * @param Request $request
     * @return mixed
     */
    public function index(Request $request)
    {
        $user = $this->auth->user();
        $where[] = ['user_id', $user->id];
        if (isset($request->order_status)) {
            //待付款
            $where[] = ['order_status', $request->order_status];
        }
        $orderList = Order::where($where)
            ->orderBy('id', 'desc')
            ->select('id', 'order_sn', 'order_status', 'goods_num', 'order_amount', 'complete_num', 'refund_num')
            ->get();
        if (count($orderList) > 0) {
            foreach ($orderList as $k => $v) {
                //订单商品
                $goodsList = DB::table('order_goods')
                    ->select('goods_title', 'goods_author', 'goods_img', 'goods_publisher', 'goods_num'
                        , 'price', 'order_user_id', 'contact_user_id', 'refund', 'id as order_goods_id')
                    ->where('order_id', $v->id)
                    ->get();
                if (count($goodsList) == 0) {
                    //过滤无效数据
                    unset($orderList->$k);
                    continue;
                }

                switch ($v->order_status) {
                    case 0:
                        $v->order_status_text = '待付款';
                        break;
                    case 1:
                        $v->order_status_text = '买家已付款';
                        break;
                    case 2:
                        $v->order_status_text = '订单已取消';
                        break;
                    case 3:
                        $v->order_status_text = '订单已过期';
                        break;
                    default:
                        $v->order_status_text = '异常';
                }
                //匹配用户
                $contact_users = DB::table('order_user as ou')
                    ->leftJoin('users as u', 'ou.contact_user_id', '=', 'u.id')
                    ->where('ou.order_id', $v->id)
                    ->select('u.head_img', 'u.nickname', 'u.phone_number',
                        'ou.id as order_user_id', 'ou.confirm_status', 'ou.trade_code')
                    ->get();
                foreach ($contact_users as $v1) {
                    $v1->goodsList = [];
                    $v1->nickname=deal_emoji($v1->nickname);
                    foreach ($goodsList as $k2 => $v2) {
                        if ($v2->order_user_id == $v1->order_user_id) {
                            $v1->goodsList[] = $v2;
                            unset($goodsList->$k2);//删除已经匹配的数据，提高效率
                        }

                    }
                }
                $v->contact_users = $contact_users;
            }
        } else {
            return $this->response->array([
                'message' => '未找到订单数据',
                'status_code' => 200,
            ]);
        }

        return $this->response->array([
            'message' => '获取订单信息成功',
            'status_code' => 200,
            'result' => $orderList
        ]);
    }

    /**
     * @param Request $request
     * @return mixed
     * 确认订单页面，需要获取，用户名，联系电话，收货地址，选择书籍信息，书籍数量，需要支付金额，可用余额，
     * 当传了goods_id 则为立即购买
     */
    public function confirmOrder(Request $request)
    {
        $user = $this->auth->user();
        if ($request->order_id) {
            //已经生成了订单
            $orderData = Order::where([['id', $request->order_id], ['user_id', $user->id], ['order_status', 0]])->first();
            if (!$orderData) {
                return $this->response->array([
                    'message' => '未找到该订单',
                    'status_code' => 201,
                ]);
            }
            $goodsList = DB::table('order_goods as og')
                ->leftJoin('goods as g', 'og.goods_id', '=', 'g.id')
                ->where('og.order_id', $orderData->id)
                ->select('og.goods_num', 'g.id', 'g.title', 'g.publisher', 'g.author', 'g.price', 'g.img', 'g.discount')
                ->get();
            $result = [
                'nickname' => deal_emoji($user->nickname),
                'phone_number' => $orderData->mobile,
                'university' => $orderData->university,
                'campus' => $orderData->campus,
                'goodsList' => $goodsList,
                'goods_num' => $orderData->goods_num,
                'totalMoney' => $orderData->order_amount,
                'extraDiscount' => $orderData->extra_discount,
                'head_img' => $user->head_img,
                'balance' => (float)$user->balance,
                'pay_amount'=>$orderData->pay_amount
            ];
            return $this->response->array([
                'message' => '确认订单信息获取成功',
                'status_code' => 200,
                'result' => $result
            ]);
        }

        $result = $this->calculateOrder($request);
        return $this->response->array($result);

    }

    //计算当前订单
    private function calculateOrder($request)
    {
        $user = $this->auth->user();
        if ($request->goods_id) {
            //立即购买，过来的
            $from = 0;
            $goodsList = Goods::where("id", $request->goods_id)
                ->select('id', 'title', 'publisher', 'author', 'price', 'img', 'discount')
                ->get();
            foreach ($goodsList as $v) {
                $v->contact_user_id = $request->contact_user_id ?: 0;//是否指定了卖家
            }
        } else {
            //购物车过来的
            $from = 1;
            $goodsList = DB::table('cart as c')
                ->leftJoin('goods as g', 'c.goods_id', '=', 'g.id')
                ->where([['c.user_id', $user->id], ['c.selected', 1], ['c.status', 0]])
                ->select('c.id as cart_id', 'c.contact_user_id', 'c.goods_num', 'g.id', 'g.title', 'g.publisher', 'g.author', 'g.price', 'g.img', 'g.discount')
                ->get();
        }
        $goodsNum = count($goodsList);
        if ($goodsNum == 0) {
            return [
                'message' => '无选中商品，获取订单信息失败',
                'status_code' => 201,
            ];
        }
        //平台折扣
        $extraDiscount = (int)WebConfig::where('name', 'extra_discount')->value('value') ?: 0;
        $totalMoney = 0;//需要支付
        foreach ($goodsList as $v) {
            $totalMoney += $v->price * ($v->discount + $extraDiscount) / 100;
            $v->goods_num = 1;//单件购买
            $v->cart_id = $v->cart_id ?: 0;//防止生成订单时报错

        }
        $result = [
            'nickname' => deal_emoji($user->nickname),
            'phone_number' => $user->phone_number,
            'university' => University::find($user->university_id)->name,
            'campus' => Campus::find($user->campus_id)->name,
            'goodsList' => $goodsList,
            'goods_num' => $goodsNum,
            'totalMoney' => $totalMoney,
            'extraDiscount' => $extraDiscount,
            'head_img' => $user->head_img,
            'balance' => (float)$user->balance,
            'from' => $from
        ];
        return [
            'message' => '确认订单信息获取成功',
            'status_code' => 200,
            'result' => $result
        ];

    }


    /**
     * 名称：生成订单
     * 必要条件：use_balance:是否使用余额,goods_id?：直接购买时，传递商品id,contact_user_id?:直接购买时指定了卖家
     * 功能：生成新的订单  ，使用calculateOrder方法去计算订单数据
     * 任务：最优匹配
     * 1.生成订单，若需要现金支付，则需要调起现金支付
     * 2.根据商品id,匹配卖书的人.匹配算法要求：最大化减少用户取书的次数。
     * 3.order_user表
     * 4.order_goods
     * 5.users
     */
    public function store(Request $request)
    {
        $user = $this->user;
        //订单已经生成，
        if ($request->order_id) {
            //生成了订单，直接去支付
            $orderData = Order::where([['id', $request->order_id], ['user_id', $user->id], ['order_status', 0]])->first();
            if (!$orderData) {
                return $this->response->array([
                    'message' => '未找到该订单',
                    'status_code' => 201,
                ]);
            }
            //需要微信支付
            $sign = $this->getSignInfo($orderData['order_sn']);
            if (!$sign['result']) {
                //获取支付签名失败
                return $this->response->array([
                    'status_code' => 201,
                    'message' => $sign['message']
                ]);
            }
            //获取支付签名成功，起调微信支付
            return $this->response->array([
                'status_code' => 200,
                'message' => $sign['message'],
                'result' => $sign['obj']
            ]);

        }
        //未生成订单
        $calculate = $this->calculateOrder($request);//当前订单数据
        if ($calculate['status_code'] != 200) {
            //获取订单失败
            return $this->response->array([
                'status_code' => 201,
                'message' => '获取订单失败'
            ]);
        }
        $data = $calculate['result'];//订单信息
        if (!$request->use_balance) {
            //当用户不使用余额的时候，将现金支付的钱，直接修改为订单总额
            $data['need_pay'] = $data['totalMoney'];
            $data['use_balance_amount'] = 0;

        } else {
            //用户使用余额
            $ca = $data['totalMoney'] - $user->balance;
            if ($ca <= 0) {
                //余额充足
                $data['need_pay'] = 0;
                $data['use_balance_amount'] = $data['totalMoney'];
            } else {
                //余额不足
                $data['need_pay'] = $ca;
                $data['use_balance_amount'] = $user->balance;//全部用光
            }

        }
        //遍历订单商品
        $goodsContrl = new GoodsController();
        $goodsStr = ',';
        if (count($data['goodsList']) == 0) {
            //莫得商品
            return $this->response->array([
                'status_code' => 201,
                'message' => '生成订单失败'
            ]);
        }
        foreach ($data['goodsList'] as $v) {
            //检查每一本书，是否本校有人在销售
            if (!$goodsContrl->checkGoodsStatus($v->id)) {
                return $this->response->array([
                    'message' => "$v->title,已售罄，请删除该书籍后再进行支付",
                    'status_code' => 201,
                ]);
            }
            $cartArr[] = $v->cart_id;//删除购物车中数据
            $tmp = [
                'goods_id' => $v->id,
                'goods_title' => $v->title,
                'goods_img' => $v->img,
                'goods_author' => $v->author,
                'goods_publisher' => $v->publisher,
                'price' => $v->price * ($v->discount + $data['extraDiscount']) / 100,
                'goods_num' => 1,
                'user_id' => $user->id,
                'contact_user_price' => $v->price * $v->discount / 100,
                'spread_user_price' => $v->price * 2 / 100,//买家的推广大使获得的利润
                'spread_contact_user_price' => $v->price * 4 / 100,//卖家的推广大使获得的利润
            ];
            if ($v->contact_user_id) {
                //指定了买家，
                $tmp['contact_user_id'] = $v->contact_user_id;
                $this->matchedData[] = $tmp;

            } else {
                //未指定买家，
                $goodsStr .= $v->id . ',';//匹配用
                $this->needMatchData[] = $tmp;
            }

        }
        if (count($this->needMatchData) > 0) {
            //有需要进行匹配的数据，数量为1的情况暂时统一处理。
            //最优匹配
            try {
                self::matchData($goodsStr);//调用此函数，查找出买家
            } catch (\Exception $exception) {
                //用错误来中止递归，有书籍未匹配成功，生成订单失败
                return $this->response->array([
                    'status_code' => 201,
                    'message' => $exception->getMessage()
                ]);
            }
        }


        //至此完成所有商品的匹配，开始数据库操作
        $rollback = false;//回滚标志
        DB::beginTransaction();//开启事物
        //生成订单
        $orderData = [
            'order_sn' => order_sn(),
            'user_id' => $user->id,
            'university' => $data['university'],
            'campus' => $data['campus'],
            'mobile' => $user->phone_number,//用户联系方式
            'order_amount' => $data['totalMoney'],
            'add_time' => time(),
            'goods_num' => $data['goods_num'],
            'order_status' => 0,//未支付,
            'use_balance_amount' => $data['use_balance_amount'],
            'use_balance_status' => $data['use_balance_amount'] ? 1 : 0,//余额支付状态，使用了余额则，会直接先扣除余额，扣除失败，则订单生成失败
            'pay_amount' => $data['need_pay'],//需要支付的现金
            'pay_status' => $data['need_pay']?1:0,//当需要支付的现金大于0时，将其改为需要现金支付
            'extra_discount' => $data['extraDiscount']//生成订单时平台折扣
        ];
        //生成订单数据
        $order_id = DB::table('order')->insertGetId($orderData);
        if (!$order_id) {
            $rollback = '商品订单id生成失败';
            goto down;
        }

        //整合数据不需要匹配的数据和已经匹配完成的数据
        $orderGoodsList = array_merge((array)$this->matchedData, (array)$this->needMatchData);
        //提取匹配到的用户
        $contact_user_ids = array_unique(array_column($orderGoodsList, 'contact_user_id'));
        if (count($contact_user_ids) == 0) {
            $rollback = '未找到卖家';
            goto down;
        } else {
            //插入订单用户表id, user_id, contact_user_id, confirm_status, send_money, order_id, comfirm_time
            foreach ($contact_user_ids as $v) {
                $tmp = [
                    'user_id' => $user->id,
                    'contact_user_id' => $v,
                    'confirm_status' => 0,
                    'send_money' => 0,
                    'order_id' => $order_id,
                    'trade_code' => rand(11111111, 99999999)//8位交易码
                ];
                $order_user_id = DB::table('order_user')->insertGetId($tmp);
                if (!$order_user_id) {
                    $rollback = '获取买家信息失败';
                    goto down;
                } else {
                    //更新$orderGoodsList数组
                    foreach ($orderGoodsList as $k1 => $v1) {
                        $orderGoodsList[$k1]['order_id'] = $order_id;
                        if ($v1['contact_user_id'] == $v) {
                            //将生成的order_user_id加入数组中
                            $orderGoodsList[$k1]['order_user_id'] = $order_user_id;
                        }
                    }
                }
            }
        }
        //锁定被匹配用户的书籍
        foreach ($orderGoodsList as $k => $v) {
            //将匹配到的用户的书籍锁定，
            $matchUserGoods = Depot::where([['user_id', $v['contact_user_id']], ['goods_id', $v['goods_id']], ['can_sale_num', '>', 0]])->first();
            if (!$matchUserGoods) {
                $rollback = '更新depot时，查询用户失败';
                goto down;
            }
            $matchUserGoods->lock_num += $v['goods_num'];
            $matchUserGoods->can_sale_num -= $v['goods_num'];
            //更新用户书架
            if (!$matchUserGoods->save()) {
                $rollback = '更新用户书架失败';
                goto down;
            }

        }
        //cart表
        if ($data['from'] == 1) {
            //购物车过来的订单,删除购物车中的数据
            foreach ($orderGoodsList as $v) {
                if (!Cart::where([['user_id', $user->id], ['goods_id', $v['goods_id']]])->update(['status' => 1])) {
                    $rollback = '更新购物车出错';
                    goto down;
                }
            }
        }

        //生成订单商品数据
        if (!DB::table('order_goods')->insert($orderGoodsList)) {
            $rollback = '生成订单商品数据失败';
            goto down;
        }
        //使用了余额，
        if ($orderData['use_balance_status'] == 1) {
            $user->balance -= $orderData['use_balance_amount'];//扣除余额
            if ($user->balance < 0 || !$user->save()) {
                $rollback = '余额扣除失败';
                goto down;
            }
            //记录日志
            if (!BalanceRecord::create([
                'user_id' => $user->id,
                'amount' => $orderData['use_balance_amount'],
                'description' => "支付订单{$orderData['order_sn']}",
                'type' => 0,
                'action' => '-'])
            ) {
                $rollback = '记录余额日志失败';
                goto down;
            }
        }


        //全部使用的余额,直接扣除余额并且调用支付成功回调函数
        if ($orderData['use_balance_amount'] == $orderData['order_amount']) {
            $res = $this->payCallBack($orderData['order_sn']);
            if (!$res['result']) {
                $rollback = 9;
                goto down;
            }
        }

        down:
        if ($rollback) {
            DB::rollback();
            if ($rollback == 9) {
                //余额支付失败
                return $this->response->array([
                    'status_code' => 201,
                    'message' => '余额支付失败'
                ]);
            }
            return $this->response->array([
                'status_code' => 201,
                'message' => '订单生成失败' . $rollback
            ]);
        } else {
            DB::commit();
        }

        if ($orderData['pay_amount'] > 0) {
            //需要微信支付
            $sign = $this->getSignInfo($orderData['order_sn']);
            if (!$sign['result']) {
                //获取支付签名失败
                return $this->response->array([
                    'status_code' => 201,
                    'message' => $sign['message']
                ]);
            } else {
                //获取支付签名成功，起调微信支付
                return $this->response->array([
                    'status_code' => 200,
                    'message' => $sign['message'],
                    'result' => $sign['obj']
                ]);
            }
        } else {
            //全部使用余额支付
            return $this->response->array([
                'status_code' => 205,
                'message' => '支付成功'
            ]);
        }

    }

    /**
     * 名称：最优匹配
     * 必要条件：此函数只用于生成订单的时候
     * 功能：递归匹配，千万考虑周全，容易死循环。功能：优先匹配同校中订单书籍来自同一个用户的
     * 任务：
     * 尽量在需要购买商品的记录中去寻找同一个买家
     */
    private function matchData($goodsStr)
    {
        $user = $this->user;
        if (!$goodsStr) {
            throw new  \Exception("没有需要购买的商品");
        }
        $tmpGoodsStr = trim($goodsStr, ',');
        $matchData = DB::table('depot')
            ->where([['university_id', $user->university_id], ['campus_id', $user->campus_id], ['can_sale_num', '>', 0], ['user_id', '!=', $user->id]])
            ->select(
                DB::raw("sum(case when goods_id in ($tmpGoodsStr) then 1 else 0 end) as matched")
                , DB::raw("GROUP_CONCAT(case when goods_id in ($tmpGoodsStr) then goods_id  end ) as matchGoodsStr")
                , 'user_id')
            ->groupBy('user_id')
            ->orderBy('matched', 'desc')
            ->first();
        //没有匹配到则需要抛出错误
        if ($matchData->matched == 0) {
            $goodsId = trim($goodsStr, ',');
            $goodsTitle = Goods::find($goodsId)->title;
            throw new  \Exception("对不起您需要的书籍《" . $goodsTitle . "》，已被别人买走啦，请在购物车中删除该书籍后重新提交订单");
        }

        $matchGoods = explode(',', $matchData->matchGoodsStr);//已经被匹配中的商品id
        foreach ($matchGoods as $v) {
            foreach ($this->needMatchData as $k1 => $v1) {
                if ($v1['goods_id'] == $v) {
                    $this->needMatchData[$k1]['contact_user_id'] = $matchData->user_id;
                }
            }
            $goodsStr = str_replace(",$v,", ",", $goodsStr);//删掉已经存入数组的数据
        }

        if (trim($goodsStr, ',')) {
            //还有需要匹配的，则递归调用
            $this->matchData($goodsStr);
        } else {
            return;
        }
    }

    /**
     * 支付成功后的逻辑处理
     * 1.更新order表
     * 2.判断时候使用余额，将冻结金额扣除，并记录日志
     * 3.向用户订单用户发送模板消息，通知支付成功
     * 4.向被匹配用户发送模板消息，通知已售出的书籍
     */
    private function payCallBack($order_sn,$out_order_num='')
    {
        if (!$order_sn) {
            return ['result' => 0, 'message' => '没有订单编号'];
        }
        $orderData = Order::where([['order_sn', $order_sn], ['order_status', 0]])->first();
        if (!$orderData) {
            return ['result' => 0, 'message' => '无效的订单编号'];
        }
        $rollback = false;//回滚标志
        DB::beginTransaction();//开启事物
        //order表
        $orderData->order_status = 1;//更改订单状态为已支付
        $orderData->pay_time = time();//支付时间
        if($orderData->use_balance_status==1){
            $orderData->use_balance_status=2;//余额改为已扣除
        }
        if($orderData->pay_status==1){
            $orderData->pay_status =2;//现金支付改为已支付
            //更新交易记录表,deal_order表
            $dealRecordData=DealRecord::where('in_order_num',$orderData->order_sn)->first();
            if($dealRecordData){
                $dealRecordData->status=1;
                $dealRecordData->out_order_num=$out_order_num;
                if(!$dealRecordData->save()){
                    $rollback = '支付成功回调，更新订单失败';
                    goto down;
                }
            }

        }

        if (!$orderData->save()) {
            $rollback = '支付成功回调，更新订单失败';
            goto down;
        }

        // 3.向用户订单用户发送模板消息，通知支付成功,不影响事物
        //创建成功，则向管理员发送模板消息
        $keyword1='';
        if($orderData->use_balance_amount>0 && $orderData->pay_amount==0){
            //只使用了余额
            $keyword1='使用余额：'.$orderData->use_balance_amount.'元';
            $keyword3='余额支付';
        }
        if($orderData->pay_amount>0 && $orderData->use_balance_amount==0){
            //只使用的现金
            $keyword1='使用现金：'.$orderData->pay_amount.'元';
            $keyword3='微信支付';
        }
        if($orderData->pay_amount>0 && $orderData->use_balance_amount>0){
            //使用了余额和现金，
            $keyword1='使用现金：'.$orderData->use_balance_amount.'元,使用余额：'.$orderData->pay_amount.'元';
            $keyword3='微信支付&余额支付';
        }

        $content1=[
            'first'=>'支付成功通知',
            'keyword1'=>$keyword1,
            'keyword2'=>date('Y-m-d H:i:s',$orderData->pay_time),
            'keyword3'=>$keyword3,
            'remark'=>'您已成功支付，请尽快联系卖家取书吧！'
        ];
        $url1=env('APP_URL').'/order?order_status=1';
        $userOpenid=User::where('id',$orderData->user_id)->value('openid');
        $this->prepareMessage($userOpenid,1,$content1,$url1);
        // 4.向卖家发送模板消息，通知已售出的书籍,不影响事物
        $content2=[
            'first'=>'您有书籍已被购买',
            'keyword1'=>'书籍售卖',
            'keyword2'=>'买家已付款',
            'keyword3'=>'您有书籍已被购买，赶紧联系买家，交书给买家，获取交易码，完成交易吧',
            'remark'=>'查看详情'
        ];
        $url2=env('APP_URL').'/customer';
        $salerOpenids=DB::table('order_user as ou')
            ->leftJoin('users as u','u.id','=','ou.contact_user_id')
            ->where('ou.order_id',$orderData->id)
            ->pluck('u.openid');
        foreach ($salerOpenids as $v){
            $this->prepareMessage($v,2,$content2,$url2);
        }

        down:
        if ($rollback) {
            DB::rollback();
            return ['result' => 0, 'message' => 'rollback:' . $rollback];
        } else {
            DB::commit();
            return ['result' => 1, 'message' => '支付回调处理成功'];
        }
    }

    /**
     * 获取支付需要签名数据
     */
    private function getSignInfo($order_sn)
    {

        if (!$order_sn) {
            return ['result' => 0, 'message' => '订单编号必须'];
        }

        $orderData = Order::where([['order_sn', $order_sn], ['order_status', 0]])->first();
        if (!$orderData) {
            return ['result' => 0, 'message' => '无效的订单'];
        }
        $dealRecord = DealRecord::where('in_order_num', $orderData->order_sn)->first();
        if (!$dealRecord) {
            $dealRecordIn = [
                'user_id' => $orderData->user_id,
                'amount' => $orderData->pay_amount,
                'status' => 0,//未支付
                'description' => '用户支付订单',
                'in_order_num' => $orderData->order_sn,
                'out_order_num' => '',
                'pay_type' => 0,//微信支付
                'type'=>0,//业务类型，书籍交易
            ];
            $dealRecord = DealRecord::create($dealRecordIn);
        }

        if (!$dealRecord) {
            return ['result' => 0, 'message' => '1.支付失败'];
        }
        $goodsNameArr = OrderGoods::where('order_id', $dealRecord->order_id)->pluck('goods_title')->toArray();

        //开始生成微信支付参数
        $attributes = [
            'trade_type' => 'JSAPI', // JSAPI，NATIVE，APP...
            'body' => '购买书籍',
            'detail' => implode(',', $goodsNameArr),
            'out_trade_no' => $dealRecord->in_order_num,
            //'total_fee' => 1, // 单位：分
            'total_fee' => $dealRecord->amount * 100, // 单位：分
            'notify_url' => env('WECHAT_NOTIFY_URL'), // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'openid'=>User::find($dealRecord->user_id)->openid,
        ];

        $order = new PayOrder($attributes);
        $payment = app('wechat')->payment;
        $result = $payment->prepare($order);
        if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS') {
            $json = $payment->configForPayment($result->prepay_id,false);
            log_arr($json);
            return ['result' => 1, 'message' => '准备支付', 'obj' => $json];
        } else {
            return ['result' => 0, 'message' => '支付失败'];

        }

    }


    /**
     * 订单回滚
     * 可回滚订单情况：
     * 1.用户30分钟未支付订单，系统自动回滚（过期订单）
     * 2.用户在未确认任何确认收货时，可通过取消订单进行回滚。(取消订单)
     *
     * 需要进行的操作
     * 1.更新订单状态,过期或者是取消
     * 3.使用了现金支付判断，将订单信息通过微信模板消息推送给管理元，由管理元进行退款
     * 4.判断是立即支付订单还是购物车订单，若为购物车订单，则将用户购物车数据进行回滚
     * 5.解锁订单所匹配到的用户的书籍。
     * $order_status,想要切换的订单状态,只支持order_status=2,3
     */
    private function orderRollBack($order_id, $order_status)
    {
        $user = $this->auth->user();
        //取出订单信息
        if (!$order_id) {
            return ['result' => 0, 'message' => '订单编号必须'];
        }

        if (!in_array($order_status, [2, 3])) {
            //目前只支持取消订单，和过期订单，操作
            return ['result' => 0, 'message' => '不支持的操作'];
        }
        $orderData = Order::find($order_id);
        //订单是否存在
        if (!$orderData) {
            return ['result' => 0, 'message' => '不存在的订单'];
        }

        if (in_array($orderData['order_stats'], [2, 3])) {
            //避免重复回滚
            return ['result' => 0, 'message' => '该订单已被回滚'];
        }
        if ($orderData->user_id != $user->id) {
            return ['result' => 0, 'message' => '您只能操作自己的订单'];

        }

        //订单状态
        $rollback = false;//回滚标志
        DB::beginTransaction();//开启事物

        //余额退回
        if ($orderData->use_balance_amount > 0) {
            $orderData->use_balance_status = 2;//已退款标志
            $user->balance += $orderData->use_balance_amount;//退款到余额
            if (!$user->save()) {
                $rollback = '退款到余额失败';
                goto down;
            }
            //日志
            if (!BalanceRecord::create([
                'user_id' => $user->id,
                'amount' => $orderData->use_balance_amount,
                'description' => "订单:{$orderData->order_sn}已被作废，您使用的余额已退还到您的账户",
                'type' => $order_status == 2 ? 5 : 7,
                'action' => '+'])
            ) {
                $rollback = '日志';
                goto down;
            }
        }

        $goodsList = DB::table('order_goods')
            ->select('goods_id', 'contact_user_id', 'goods_num')
            ->where('order_id', $orderData->id)
            ->get();
        foreach ($goodsList as $v) {
            //解锁订单所匹配到的用户的书籍。
            $depot = Depot::where([['goods_id', $v->goods_id], ['user_id', $v->contact_user_id]])->first();
            $depot->lock_num -= $v->goods_num;
            $depot->can_sale_num += $v->goods_num;
            if (!$depot->save()) {
                $rollback = '更新用户书架失败';
                goto down;
            }
        }

        //切换订单状态
        $orderData->order_status = $order_status;
        if (!$orderData->save()) {
            $rollback = '切换订单状态失败';
            goto down;
        }


        down:
        if ($rollback) {
            DB::rollback();
            return ['result' => 0, 'msg' => $rollback];

        } else {
            DB::commit();
            return ['result' => 1, 'msg' => '更新订单状态成功'];

        }

    }

    /**
     * 名称：取消订单接口
     * 必要条件：order_id，
     * 功能：针对未支付的订单（order_status=0）,用户直接取消订单
     * 任务：
     * 1.检查订单是否使用的余额进行支付，回滚，并记录日志，
     * 2.回滚商品库存
     * 3.发送系统消息,提醒用户订单已取消
     */
    public function cancelOrder($order_id)
    {
        $user = $this->auth->user();
        //查询未支付的订单
        $orderData = Order::where([['id', $order_id], ['user_id', $user->id], ['order_status', 0]])->first();
        if (!$orderData) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '1.操作失败'
            ]);
        }

        $res = $this->orderRollBack($order_id, 2);//取消订单
        if (!$res['result']) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '2.操作失败'
            ]);
        }

        //发送系统消息提醒用户订单已取消
        Notice::create([
            'title'=>'订单取消',
            'content'=>'您已成功取消了订单:'.$orderData->order_sn.'。该订单包括以下书籍：'.getOrderGoodsName($orderData->id),
            'readed'=>0,
            'user_id'=>$orderData->user_id,
            'url'=>env('APP_URL').'/order'
        ]);

        return $this->response->array([
            'status_code' => 200,
            'message' => '操作成功'
        ]);
    }

    /**
     * 删除订单
     * 只能删除过期的，或者取消了的订单
     */
    public function destory($order_id)
    {
        $user = $this->auth->user();
        $order_status = Order::where([['id', $order_id], ['user_id', $user->id]])->value('order_status');
        if (!in_array($order_status, [2, 3])) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '该订单状态不支持删除'
            ]);
        }
        $rollback = false;//回滚标志
        DB::beginTransaction();//开启事物
        if (!Order::where('id', $order_id)->delete()) {
            $rollback = '删除order表失败';
            goto down;
        }
        if (!OrderGoods::where('order_id', $order_id)->delete()) {
            $rollback = '删除orderGoods表失败';
            goto down;

        }
        if (!OrderUser::where('order_id', $order_id)->delete()) {
            $rollback = '删除orderUser表失败';
            goto down;

        }
        down:
        if ($rollback) {
            DB::rollback();
            return $this->response->array([
                'status_code' => 201,
                'message' => '删除失败'
            ]);

        } else {
            DB::commit();
            return $this->response->array([
                'status_code' => 200,
                'message' => '删除成功'
            ]);

        }

    }

    /**
     * 确认发货，针对卖家,交易已完成，
     * 必要条件：对应的订单状态必须为已支付,子单未确认收货,未向用户打钱,本人操作，交易码正确
     * 任务：
     * 1.更新order_goods confirm_status
     * 2.检查用户所有子单是否都已确认收货完毕，若是则将订单状态修改为已完成
     * 3.更新order confirm_status,代表已有子单被确认，用户不能取消订单
     * 4.给确认的已发书籍的用户增加余额
     * 5.记录日志
     * 6.更新售卖书籍的用户书籍存量
     * 7.确认交易成功是推送系统消息给买家和卖家
     *
     */
    public function confirmSendGoods(Request $request)
    {
        $user = $this->auth->user();//本人操作
        $order_user_id = $request->order_user_id;//卖家订单表id
        $trade_code = $request->trade_code;//交易码
        //检查请求参数
        if (!$order_user_id || !$trade_code) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '1.确认交易失败'
            ]);
        }

        //操作数据
        $orderUserData = OrderUser::find($order_user_id);
        if (!$orderUserData) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '2.确认交易失败'
            ]);
        }
        //本人操作
        if ($orderUserData->contact_user_id != $user->id) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '3.确认交易失败'
            ]);
        }
        //记录状态必为待用户取书
        if ($orderUserData->confirm_status != 0) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '4.确认交易失败'
            ]);
        }
        //比对交易码
        if ($orderUserData->trade_code != $trade_code) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '交易码错误'
            ]);
        }

        //对应订单状态必须为已支付
        $orderData = Order::where([['id', $orderUserData->order_id], ['order_status', 1]])->first();
        if (!$orderData) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '5.确认交易失败'
            ]);
        }

        $rollback = false;//回滚标志
        DB::beginTransaction();//开启事物

        //给确认的已发书籍的用户增加余额
        $orderGoodsList = OrderGoods::where([['order_user_id', $order_user_id], ['contact_user_id', $user->id]])->get();
        $balanceLogText = '';//交易的书籍，记录日志和发送系统消息均要使用
        $totalMoney = 0;
        foreach ($orderGoodsList as $v) {
            if ($v->refund == 1) {
                //有退款订单未处理
                return $this->response->array([
                    'status_code' => 201,
                    'message' => '6.确认交易失败:' . $v->goods_title . '有退款申请，请您先进行处理'
                ]);
            }
            //计算状态为正常，和拒绝退款的订单
            if (in_array($v->refund, [0, 3])) {
                $totalMoney += $v->contact_user_price * $v->goods_num;
            }
            if ($v->refund != 2) {
                //除开退款的
                $balanceLogText .= $v->goods_title . ',';
            }
            //更新售卖书籍的用户书籍存量，对于已经退款了的则不做处理
            if($v->refund!=2){
                $depot = Depot::where([['user_id', $v->contact_user_id], ['goods_id', $v->goods_id]])->first();
                $depot->total -= $v->goods_num;//总量减少
                $depot->lock_num -= $v->goods_num;//锁定数量减少
                if (!$depot->save()) {
                    $rollback = '7.确认交易失败';
                    goto down;
                }
            }


        }
        //订单数据
        $orderData->complete_num++;
        //计算此子单是否为订单的最后一个子单
        $childOrderNum = OrderUser::where('order_id', $orderUserData->order_id)->count();
        if($orderData->complete_num==$childOrderNum){
            $lastChildOrder=true;
        }else{
            $lastChildOrder=false;
        }
        //计算返利
        if (web_config('spread')) {
            //读取配置，需要返利,卖家的推广大使。
            $spreadUserForSaler = $user->spread_uid ? User::find($user->spread_uid) : null;//卖家的推广大使
            $userOrderCount = OrderUser::where('contact_user_id', $user->id)->count();//计算当期卖家是第几单。
            if ($spreadUserForSaler && $userOrderCount == 1) {
                //卖家的推广大使存在， 且当前卖家是第一单，需要获得返利。
                $orderUserData->spread_amount = OrderGoods::where([['order_user_id', $orderUserData->id], ['refund', '!=', 2]])->sum('spread_contact_user_price');
                if ($orderUserData->spread_amount > 0) {
                    //返利金额大于0，需要返利
                    $orderUserData->spread_status = 1;//已返利
                    $spreadUserForSaler->balance += $orderUserData->spread_amount;//增加卖家的推广大使的余额
                    if (!$spreadUserForSaler->save()) {
                        $rollback = '12.确认交易失败';
                        goto down;
                    }
                    //余额日志
                    if (!BalanceRecord::create([
                        'user_id' => $spreadUserForSaler->id,
                        'amount' => $orderUserData->spread_amount,
                        'description' => '因推广校友而产生收益',
                        'type' => 4,//作为推荐人，用户上架书籍，卖出第一笔订单，获得返利。
                        'bespread_uid' => $user->id,//当前被推广的用户id
                        'action' => '+'])
                    ) {
                        $rollback = '13.确认交易失败';
                        goto down;
                    }

                }

            } else {
                $orderUserData->spread_amount = 0;
                $orderUserData->spread_status = 2;//需要返利
            }
            //买家的推广大使
            $spreadUserForUserId = User::where('id', $orderUserData->user_id)->value('spread_uid') ?: 0;
            $spreadUserForUser = $spreadUserForUserId ? User::find($spreadUserForUserId) : null;//买家的推广大使

            if ($spreadUserForUser && $lastChildOrder) {
                //买家有推广大使，且订单已全部确认完成。
                $orderData->spread_amount = OrderGoods::where([['order_id', $orderData->id], ['refund', '!=', 2]])->sum('spread_user_price');
                if ($orderData->spread_amount > 0) {
                    //返利金额大于0，需要返利
                    $orderData->spread_status = 1;//已返利
                    $spreadUserForUser->balance += $orderData->spread_amount;//增加买家的推广大使的余额
                    if (!$spreadUserForUser->save()) {
                        $rollback = '14.确认交易失败';
                        goto down;
                    }
                    //余额日志
                    if (!BalanceRecord::create([
                        'user_id' => $spreadUserForUser->id,
                        'amount' => $orderData->spread_amount,
                        'description' => '因推广校友而产生收益',
                        'type' => 2,//作为推荐人，用户购买书籍，获得返利
                        'bespread_uid' => $orderUserData->user_id,//当前被推广的用户id
                        'action' => '+'])
                    ) {
                        $rollback = '15.确认交易失败';
                        goto down;
                    }

                }
            } else {
                $orderData->spread_amount = 0;
            }
        }



        //orderUser表，确认发货。
        $orderUserData->confirm_status = 1;//确认发货
        $orderUserData->comfirm_time = time();//确认发货时间
        $orderUserData->send_money = $totalMoney;//卖家获得的钱
        if (!$orderUserData->save()) {
            $rollback = '8.确认交易失败';
            goto down;
        }

        if($lastChildOrder){
            //最后一个子单，计算平台收益。平台收益=买家支付-买家推广大使-卖家收入-卖家推广大使
            $orderUserSum=OrderUser::where('order_id',$orderData->id)->sum('send_money')+OrderUser::where('order_id',$orderData->id)->sum('spread_amount');;
            $income=$orderData->order_amount-$orderData->spread_amount-$orderUserSum;
            if(!PlatformIncome::create([
                'in_order_num'=>$orderData->order_sn,
                'amount'=>$income,
                'description'=>'书籍交易收入',
                'type'=>0
            ])){
                $rollback = '17.确认交易失败';
                goto down;
            }
        }

        if (!$orderData->save()) {
            $rollback = '13.确认交易失败';
            goto down;
        }



        $user->balance += $totalMoney;//增加当前用户的余额
        if (!$user->save()) {
            $rollback = '9.确认交易失败';
            goto down;
        }
        //记录日志
        if (!BalanceRecord::create([
            'user_id' => $user->id,
            'amount' => $totalMoney,
            'description' => '售卖书籍：'.$balanceLogText,
            'type' => 8,
            'action' => '+'])
        ) {
            $rollback = '10.确认交易失败';
            goto down;
        }


        down:
        if ($rollback) {
            DB::rollback();
            return $this->response->array([
                'status_code' => 201,
                'message' => $rollback
            ]);

        } else {
            //推送系统消息给卖家
            Notice::create([
                'title'=>'书籍售卖成功',
                'content'=>'恭喜您已售卖出书籍：'.$balanceLogText,
                'readed'=>0,
                'user_id'=>$orderUserData->contact_user_id,
                'url'=>env('APP_URL').'/customer?status=1'
            ]);
            //推送系统消息给买家
            Notice::create([
                'title'=>'书籍获取成功',
                'content'=>'您已成功获取书籍：'.$balanceLogText,
                'readed'=>0,
                'user_id'=>$orderUserData->user_id,
                'url'=>env('APP_URL').'/order?order_status=3'
            ]);
            DB::commit();
            return $this->response->array([
                'status_code' => 200,
                'message' => '确认交易成功'
            ]);

        }

    }

    /**
     * 名称：退款，
     * 必要条件：$order_goods_id，只能是已支付的订单
     * 功能：用户针对商品发起退款操作
     * 任务：
     * 1.更新order_goods表的refund字段
     * 2.记录用户发起退款次数
     * 3.检查子单中的商品，是否所有的都已被退款，若所有已被退款，则将子单更新为已完成
     */
    public function refund($order_goods_id)
    {
        $user = $this->auth->user();
        $orderGoods = OrderGoods::find($order_goods_id);
        if (!$orderGoods) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '不存在的订单商品记录'
            ]);
        }
        if (!in_array($orderGoods->refund, [0, 3])) {
            //当前退款字段只能是0,3,，0：正常状态，3：卖家拒绝退款
            return $this->response->array([
                'status_code' => 201,
                'message' => '非法操作'
            ]);
        }
        //验证是否本人在操作
        if ($user->id != $orderGoods->user_id) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '您只能操作您自己的订单商品'
            ]);
        }
        //检查订单是否支付
        $orderStatus = Order::where('id', $orderGoods->order_id)->value('order_status');
        if ($orderStatus != 1) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '未支付的订单'
            ]);
        }

        //开始更新数据
        $orderGoods->refund = 1;//买家申请退款
        $orderGoods->refund_times++;//记录申请退款次数
        if ($orderGoods->save()) {
            //用户申请退款，发送系统消息给用户自己，同时，发送模板消息给对应卖家
            //发送系统消息给自己
            Notice::create([
                'title'=>'提交退款',
                'content'=>'您已成功提交了退款申请，我们已通知卖家处理，您也可自行联系卖家为您尽快处理。退款书籍：'.$orderGoods->goods_title,
                'readed'=>0,
                'user_id'=>$orderGoods->user_id,
                'url'=>env('APP_URL').'/order?order_status=1'
            ]);

            //发送模板消息给卖家，通知卖家处理
            $content=[
                'first'=>'您有退款申请需要处理',
                'keyword1'=>'退款处理',
                'keyword2'=>'待处理',
                'keyword3'=>'退款书籍：'.$orderGoods->goods_title.'。书籍退款后。书籍锁定状态会被解除，以待其他买家购买。',
                'remark'=>'请尽快处理退款，等待其他买家购买'
            ];
            $url=env('APP_URL').'/customer';
            $userOpenid=User::where('id',$orderGoods->contact_user_id)->value('openid');
            $this->prepareMessage($userOpenid,2,$content,$url);
            return $this->response->array([
                'status_code' => 200,
                'message' => '操作成功'
            ]);
        } else {
            return $this->response->array([
                'status_code' => 201,
                'message' => '操作失败，服务器发生内部错误'
            ]);
        }


    }

    /**
     * 名称：卖家处理退款
     * 必要条件：order_goods_id,refund，当前退款记录refund=1,卖家才能操作，
     * 功能：卖家处理退款，同意退款||拒绝退款
     * 任务：
     * 1.当卖家同意退款时，需要回滚商品库存
     */
    public function dealRefund(Request $request)
    {
        $user = $this->auth->user();
        //检查请求参数
        if (!$request->order_goods_id || !in_array($request->refund, [2, 3])) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '请求参数错误'
            ]);
        }
        //获取数据记录
        $orderGoods = OrderGoods::find($request->order_goods_id);
        if (!$orderGoods) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '不存在的记录'
            ]);
        }
        //验证是否本人操作
        if ($user->id != $orderGoods->contact_user_id) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '您没有权限操作该条记录'
            ]);
        }
        //只能处理申请退款的状态
        if ($orderGoods->refund != 1) {
            return $this->response->array([
                'status_code' => 201,
                'message' => '非法操作'
            ]);
        }

        if ($request->refund == 3) {
            //卖家拒绝退款,只需要更新order_goods表
            $orderGoods->refund = 3;
            if (!$orderGoods->save()) {
                return $this->response->array([
                    'status_code' => 201,
                    'message' => '操作失败，服务器发送错误'
                ]);
            } else {
                //发送模板消息给卖家，通知卖家处理
                $content=[
                    'first'=>'退款处理通知',
                    'keyword1'=>'退款申请',
                    'keyword2'=>'退款已被卖家拒绝',
                    'keyword3'=>'您可联系卖家协商，再次发起退款。若不能协商，请联系我们的客服。',
                    'remark'=>'温馨提示：若卖家，拒绝退款，则您可拒绝提供交易码于卖家。'
                ];
                $url=env('APP_URL').'/order?order_status=1';
                $userOpenid=User::where('id',$orderGoods->user_id)->value('openid');
                $this->prepareMessage($userOpenid,2,$content,$url);
                return $this->response->array([
                    'status_code' => 200,
                    'message' => '操作成功'
                ]);
            }
        }
        //卖家同意退款，需要进行退钱，记录日志，回滚商品库存操作
        $rollback = false;//回滚标志
        DB::beginTransaction();//开启事物
        //1.更新订单商品状态
        $orderGoods->refund = 2;//卖家同意退款
        if (!$orderGoods->save()) {
            $rollback = '1.操作失败';
            goto down;
        }
        //2.退钱
        $toUser = User::find($orderGoods->user_id);//买家
        $toUser->balance += $orderGoods->price;
        if (!$toUser->save()) {
            $rollback = '2.操作失败';
            goto down;
        }
        //3.日志
        $balanceLogText = '卖家同意退款,书籍：《' . $orderGoods->goods_title . '》';
        if (!BalanceRecord::create([
            'user_id' => $toUser->id,
            'amount' => $orderGoods->price,
            'description' => $balanceLogText,
            'type' => 7,
            'action' => '+'])
        ) {
            $rollback = '3.操作失败';
            goto down;
        }

        //4.回滚商品库存
        $depot = Depot::where([['user_id', $orderGoods->contact_user_id], ['goods_id', $orderGoods->goods_id]])->first();
        $depot->lock_num -= $orderGoods->goods_num;
        $depot->can_sale_num += $orderGoods->goods_num;
        if (!$depot->save()) {
            $rollback = '4.操作失败';
            goto down;
        }

        //5.检查子单中是否所有的商品都已退款。若所有商品都已退款则，将子单状态更新为已完成
        if ($request->refund == 2) {
            $order = Order::find($orderGoods->order_id);
            $order->refund_num++;
            //当前处理为同意退款时，才去检查
            $orderGoodsNum = OrderGoods::where('order_user_id', $orderGoods->order_user_id)->count();//子弹商品总数
            $orderGoodsRefundNum = OrderGoods::where([['order_user_id', $orderGoods->order_user_id], ['refund', 2]])->count();//已退款数量
            if ($orderGoodsNum == $orderGoodsRefundNum) {
                //当前子单已全部退款
                $orderUser = OrderUser::find($orderGoods->order_user_id);
                $orderUser->confirm_status = 1;//已完成
                $orderUser->comfirm_time = time();
                if (!$orderUser->save()) {
                    $rollback = '5.操作失败';
                    goto down;
                }
                $order->complete_num++;
            }

            if (!$order->save()) {
                $rollback = '6.操作失败';
                goto down;
            }

        }
        down:
        if ($rollback) {
            DB::rollback();
            return $this->response->array([
                'status_code' => 201,
                'message' => $rollback
            ]);

        } else {
            DB::commit();
            $content=[
                'first'=>'退款处理通知',
                'keyword1'=>'退款申请',
                'keyword2'=>'买家已同意退款',
                'keyword3'=>'退款金额已退还到您的余额账户。您可提现到您的微信余额。退款金额：'.$orderGoods->price.'元。',
                'remark'=>''
            ];
            $url=env('APP_URL').'/user';
            $userOpenid=User::where('id',$orderGoods->user_id)->value('openid');
            $this->prepareMessage($userOpenid,2,$content,$url);
            return $this->response->array([
                'status_code' => 200,
                'message' => '操作成功'
            ]);

        }

    }

    /**
     * 名称：书籍交易微信支付成功回调
     */
    public function wechatPayback()
    {
        $wechat=app('wechat');
        $response = $wechat->payment->handleNotify(function($notify, $successful){
            log_arr($notify);
            if($successful){
                $res=$this->payCallBack($notify->out_trade_no,$notify->transaction_id);
                if($res['result']){
                    return true;
                }
            }
            return false; // 或者错误消息
        });

        return $response; // Laravel 里请使用：return $response;
    }



}